package gcontent.entities.content.dns;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.xbill.DNS.Name;
import org.xbill.DNS.ZoneTransferIn;
import gcontent.channel.dns.ChannelDNS;
import gcontent.channel.error.ChannelEx;
import gcontent.entities.Content; 
import gcontent.entities.Site;
import gcontent.entities.site.SiteURL;

public class ContentDNS extends Content {
	public static final String TYPE_DNS = "DNS";	
	private ArrayList<String> visited_sites;
	private ArrayList<String> unvisited_sites;
	private static final String [] records = {"NS"}; //, "A", "SOA", "MX", "AAAA", "CNAME", "PTR", "SRV", "TXT"};
	
	private void initHostDir()
	{
		/* get host from URL */
		visited_sites = new ArrayList<String>();
		unvisited_sites = new ArrayList<String>();
	}
	
	private void registerSites() 
	{
		String domain = new String(this.body);
		unvisited_sites = new ArrayList<String>();
		ArrayList<String> unvisited_copy = null;
		ZoneTransferIn xfr = null;
		Name name = null;
		String ip = "";
		List items = null;
		Iterator iter;
				
		// Print the DNS zones
		try {
			ip = gcontent.utils.IP.getIpAddress("this.getParentSite().getPath()");
			name = new Name(gcontent.utils.URLUtils.splitProtocol("this.getParentSite().getPath()"));
			
			System.out.println("Trying to find hosts in '" + "this.getParentSite().getPath()" + "'...");
			
			xfr = ZoneTransferIn.newAXFR(name, ip, null);
			items = xfr.run();
			for (iter = items.iterator(); iter.hasNext(); )
				System.out.println("\t\t" + iter.next());
		} catch (Exception ex) {
			System.out.println("\t\tNo xfr records found on this server: " + ex.toString());		
		}
		
		// Get the domain NS records
		for (int i = 0; i < records.length; i++) {
			int idx = domain.indexOf(records[i] + ":");
			int idx_last = domain.indexOf('\n');
			String [] elements = null;;
			String sub_body = "";
			
			if (idx != -1) {
				sub_body = domain.substring(idx + new String(records[i] + ":").length(), idx_last);
				elements = sub_body.split(";");
				
				if (elements != null) {
					String node = "";
					
					// We only want domain names, not ips
					for (int j = 0; j < elements.length; j++) {
						try {
							node = gcontent.utils.IP.NormalizeAddress(elements[j]).getHostName();
						} catch (Exception ex) {
							node = "";
						}
						// If we don't have it, we store it
						if (!node.equals(""))
							if (!isInVisitedList(node))
								unvisited_sites.add(node);	
					}					
				}	
				domain = domain.substring(idx_last + 1);
			}	
		}
		
		// Print dns site and its child number
		System.out.println("this.getParentSite().getPath()" + " {" + unvisited_sites.size() + "}");
		for (int i = 0; i < unvisited_sites.size(); i++) {
			System.out.println("\t" + unvisited_sites.get(i));
		}
		
		// Visit other sites
		unvisited_copy = unvisited_sites;
		for (int i = 0; i < unvisited_copy.size(); i++) {			
			// Register as visited
			if (!visited_sites.contains((unvisited_copy.get(i)))) {
				visited_sites.add(unvisited_copy.get(i));
			
				ChannelDNS dns = new ChannelDNS();
				String newContent = null;
				Site site = null;
				try {
					site = new Site();
					//("dns:/" + "unvisited_copy.get(i)");
					unvisited_copy.set(i, "");
					
					dns.connect(site);
					this.setParentSite(site);
					newContent = dns.getStringContent();
					this.body = newContent.getBytes();
					this.registerSites();				
				} catch (ChannelEx e) {
					e.printStackTrace();
				}
			} else {
				System.out.println("Visited before => " + unvisited_copy.get(i));				
			}
		}
	}

	private boolean isInVisitedList(String item) {
		return visited_sites.contains(item);
	}
	
	public void parse()
	{
		initHostDir();
		registerSites();
	}
}